using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Runtime.CompilerServices;
using viBook.Common;
using viBook.Models;

namespace viBook.Repositories
{
    public class ChapterRepository : IChapterRepository
    {
        private readonly viBookContext _context;
        private readonly IPageRepository _pagerepository;

        public ChapterRepository(IPageRepository pageRepository)
        {
            _context = new viBookContext();
            _pagerepository = pageRepository;
        }

        #region IChapterRepository Members

        public IQueryable<Chapter> All
        {
            get { return _context.Chapters; }
        }

        public Chapter Find(int id, int userId)
        {
            var chapter = _context.Chapters.Find(id);
            if (chapter != null)
            {
                IQueryable<ChapterComment> totalComments = _context.ChapterComments.Where(c => c.ChapterId == id && !c.IsBlocked);
                var comments =
                    totalComments.OrderByDescending(c => c.CreatedDate).Take(Constant.MaximunCommentPerChapter).Include(
                        c => c.User).ToList();
                int noOfComments = totalComments.Count();
                foreach (ChapterComment chapterComment in comments)
                {
                    chapterComment.IsLiked =
                        _context.ChapterCommentLikes.Any(bcl => bcl.CommentId == chapterComment.Id && bcl.UserId == userId);
                    chapterComment.IsReported =
                        _context.ReportOnChapterComments.Any(
                            rocc => rocc.ChapterCommentId == chapterComment.Id && rocc.UserId==userId);
                    chapterComment.IsAuthorized = (chapterComment.UserId == userId);
                }
                chapter.Comments = comments;
                chapter.NumberOfLikes = _context.ChapterLikes.Count(cl => cl.ChapterId == id);
                chapter.IsLiked = _context.ChapterLikes.Any(cl => cl.ChapterId == id && cl.UserId == userId);
                chapter.NumberOfComments = noOfComments;
                chapter.NumberOfViews++;
                chapter.Pages = new List<Page>();
                chapter.Pages = _context.Pages.Where(p => p.ChapterId == chapter.Id).OrderBy(p => p.Number).ToList();
                foreach (var page in chapter.Pages)
                {
                    page.Tags = _context.Tags.Where(t => t.PageId == page.Id).ToList();
                }
                Book book = _context.Books.Find(chapter.BookId);
                book.AuthorName = _context.Authors.Find(book.AuthorId).AuthorName;
                book.ContentTags = new List<ContentTag>();
                book.Uploader = _context.Users.Find(book.UploadedBy);
                chapter.Book = book;
                var prevChapter = _context.Chapters.FirstOrDefault(c => c.BookId == chapter.BookId && c.ChapterNumber == chapter.ChapterNumber - 1);
                var nextChapter = _context.Chapters.FirstOrDefault(c => c.BookId == chapter.BookId && c.ChapterNumber == chapter.ChapterNumber + 1);
                if (prevChapter != null)
                {
                    chapter.PreviousChapterId = prevChapter.Id;
                    chapter.PreviousChapterName = prevChapter.ChapterName;
                }

                if (nextChapter != null)
                {
                    chapter.NextChapterId = nextChapter.Id;
                    chapter.NextChapterName = nextChapter.ChapterName;
                }
            }
            return chapter;
        }

        public Chapter Find(int id)
        {
           return _context.Chapters.Find(id);
        }

        //todo:doing edit chapter
        public void InsertOrUpdate(Chapter chapter)
        {
            if (chapter.Id == default(int))
            {
                chapter.UploadedDate = DateTime.Now;
                chapter.ChapterNumber = _context.Chapters.Where(c => c.BookId == chapter.BookId).ToList().Count() + 1;
                _context.Chapters.Add(chapter);
             
                int numpage = 0;
                foreach (Page page in chapter.Pages)
                {
                    numpage = numpage + 1;
                    page.Number = numpage;
                }
                Save();
            }
            else
            {
                if (!string.IsNullOrEmpty(chapter.ListSortedPagesId))
                {
                    string[] listPageId = chapter.ListSortedPagesId.Split(new[] { ';' },
                                                                            StringSplitOptions.RemoveEmptyEntries);
                    int pageNumber = 0;
                    foreach (string pageId in listPageId)
                    {
                        pageNumber++;
                        Page page = _pagerepository.Find(int.Parse(pageId));
                        page.Number = pageNumber;
                        _pagerepository.InsertOrUpdate(page);
                        _pagerepository.Save();
                        if(pageNumber==1)
                        {
                            chapter.ChapterImage = page.ImageSource;
                        }
                    }
                }
                _context.Entry(chapter).State = EntityState.Modified;
                Save();
            }
        }

        //todo:edit chapters
        public void Delete(int id)
        {
            Chapter chapter = _context.Chapters.Find(id);
            _pagerepository.DeletePagesInChapter(id);
            Helpers.Helpers.DeleteFile(chapter.ChapterImage);
            _context.Chapters.Remove(chapter);
        }

        public void Save()
        {
            _context.SaveChanges();
        }

        public void Like(int chapterId, int userId)
        {
            var chapterLike = new ChapterLike
                                  {
                                      ChapterId = chapterId,
                                      CreatedDate = DateTime.Now,
                                      UserId = userId
                                  };
            _context.ChapterLikes.Add(chapterLike);
            Chapter chapter = _context.Chapters.Find(chapterId);
            chapter.NumberOfLikes++;
            InsertOrUpdate(chapter);
            Save();
        }

        public void DeleteChaptersInBook(int id)
        {
            List<int> listChapterId = _context.Chapters.Where(c => c.BookId == id).Select(c => c.Id).ToList();
            foreach (int chapterid in listChapterId)
            {
                _pagerepository.DeletePagesInChapter(chapterid);
                Delete(chapterid);
                Save();
            }
        }

        public void UnLike(int chapterId, int userId)
        {
            ChapterLike chapterLike =
                _context.ChapterLikes.FirstOrDefault(cl => cl.ChapterId == chapterId && cl.UserId == userId);
            if (chapterLike != null)
                _context.ChapterLikes.Remove(chapterLike);
            Chapter chapter = _context.Chapters.Find(chapterId);
            chapter.NumberOfLikes--;
            InsertOrUpdate(chapter);
            Save();
        }

        public IQueryable<Chapter> GetAllChaptersByBookId(int bookId)
        {
            return _context.Chapters.
                Where(c => c.BookId == bookId).OrderBy(c => c.ChapterNumber);
        }

        #endregion
    }

    public interface IChapterRepository
    {
        IQueryable<Chapter> All { get; }
        Chapter Find(int id, int userId);
        Chapter Find(int id);
        void InsertOrUpdate(Chapter chapter);
        void Delete(int id);
        void Save();
        IQueryable<Chapter> GetAllChaptersByBookId(int bookId);

        void Like(int chapterId, int userId);
        void DeleteChaptersInBook(int id);
        void UnLike(int chapterId, int userId);
    }
}